package org.jeecg.modules.icms.customs.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.icms.customs.dto.IcmsCustomsDetailDto;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsBrief;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsDetail;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsElements;
import org.jeecg.modules.icms.customs.entity.IcmsCustomsHeader;
import org.jeecg.modules.icms.customs.mapper.IcmsCustomsBriefMapper;
import org.jeecg.modules.icms.customs.mapper.IcmsCustomsDetailMapper;
import org.jeecg.modules.icms.customs.mapper.IcmsCustomsElementsMapper;
import org.jeecg.modules.icms.customs.mapper.IcmsCustomsHeaderMapper;
import org.jeecg.modules.icms.customs.service.IIcmsCustomsElementsService;
import org.jeecg.modules.icms.util.HandleExcelInfo;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 申报要素
 * @Author: jeecg-boot
 * @Date: 2024-01-10
 * @Version: V1.0
 */
@Service
public class IcmsCustomsElementsServiceImpl extends ServiceImpl<IcmsCustomsElementsMapper, IcmsCustomsElements> implements IIcmsCustomsElementsService {

    public static final int ELEMENT_SHEET_INDEX = 0;
    public static final int BRIEF_SHEET_INDEX = 1;
    public static final int DETAIL_SHEET_INDEX = 2;

    @Resource
    private IcmsCustomsHeaderMapper icmsCustomsHeaderMapper;
    @Resource
    private IcmsCustomsBriefMapper icmsCustomsBriefMapper;
    @Resource
    private IcmsCustomsDetailMapper icmsCustomsDetailMapper;
    @Resource
    private HandleExcelInfo handleExcelInfo;

    @Override
    public Result<?> importForSheets(MultipartFile file) throws Exception {
        //根据file得到Workbook,主要是要根据这个对象获取,传过来的excel有几个sheet页
        Workbook workbook = handleExcelInfo.getWorkBook(file);
        //获取sheet数量
        int sheetNum = workbook.getNumberOfSheets();
        if (sheetNum == 0) {
            throw new JeecgBootException("导入文件为空！");
        }

        List<IcmsCustomsElements> elementList = new ArrayList<>();
        List<IcmsCustomsBrief> briefList = new ArrayList<>();
        List<IcmsCustomsDetail> detailList = new ArrayList<>();
        List<IcmsCustomsDetailDto> detailDtoList = new ArrayList<>();
        //定义标题
        String titleElement = null;
        //定义合同号
        String contractNo = null;
        //定义出口国家
        String exportCompany = null;
        String headerId = null;
        //遍历多sheets,根据遍历出来的sheet名分别做处理
        for (int sheetIndex = 0; sheetIndex < sheetNum; sheetIndex++) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            ImportParams params = new ImportParams();
            params.setTitleRows(1);
            params.setHeadRows(1);
            //第几个sheet页
            params.setStartSheetIndex(sheetIndex);
            params.setSheetNum(1);
            //1-处理“申报要素（导入）”数据入库
            if (ELEMENT_SHEET_INDEX == sheetIndex) {
                //获取标题内容，截取其中的出口国家和合同号
                titleElement = sheet.getRow(0).getCell(0).toString();
                //合同号
                contractNo = titleElement.substring(0, titleElement.indexOf("+"));
                //出口国家
                exportCompany = titleElement.substring(titleElement.indexOf("+") + 1, titleElement.indexOf("—"));
                //获取表头下的数据
                List<IcmsCustomsElements> elementTemps = ExcelImportUtil.importExcel(file.getInputStream(),
                        IcmsCustomsElements.class, params);
                for (IcmsCustomsElements ele : elementTemps) {
                    if (!handleExcelInfo.checkObjAllFieldsIsNull(ele)){
                        elementList.add(ele);
                    }
                }
                //将sheet遍历成List后统一处理关联关系后入库
                //获取合同号做校验，不能与报关头表中已有合同号重复
                List<IcmsCustomsHeader> icmsCustomsHeaderList = icmsCustomsHeaderMapper.selectList(null);
                Map<String, IcmsCustomsHeader> mapHeader = icmsCustomsHeaderList.stream()
                        .collect(Collectors.toMap(IcmsCustomsHeader::getContractNo, Function.identity()));
                if (mapHeader.containsKey(contractNo)) {
                    throw new JeecgBootException("合同号重复，请检查导入文件");
                }
                //获取报关头id
                IcmsCustomsHeader icmsCustomsHeader = new IcmsCustomsHeader();
                icmsCustomsHeader.setContractNo(contractNo);
                icmsCustomsHeader.setExportCountry(exportCompany);
                //默认为0：未匹配
                icmsCustomsHeader.setMatchFlag("0");
                icmsCustomsHeaderMapper.insert(icmsCustomsHeader);
                QueryWrapper<IcmsCustomsHeader> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(IcmsCustomsHeader::getContractNo, contractNo)
                        .eq(IcmsCustomsHeader::getExportCountry, exportCompany)
                        .eq(IcmsCustomsHeader::getMatchFlag, 0);
                headerId = icmsCustomsHeaderMapper.selectOne(queryWrapper).getId();
                //处理【申报要素】
                String elementContractNo = contractNo;
                String elementExportCompany = exportCompany;
                String elementHeaderId = headerId;
                elementList.forEach(element -> {
                    element.setCustomsHeaderId(elementHeaderId);
                    element.setContractNo(elementContractNo);
                    element.setExportCompany(elementExportCompany);
                    baseMapper.insert(element);
                });
            }
            //2-处理“分类简表（导入）”数据入库
            if (BRIEF_SHEET_INDEX == sheetIndex) {
                //获取表头下的数据
                List<IcmsCustomsBrief> briefTemps = ExcelImportUtil.importExcel(file.getInputStream(),
                        IcmsCustomsBrief.class, params);
                for (IcmsCustomsBrief brief : briefTemps) {
                    if (!handleExcelInfo.checkObjAllFieldsIsNull(brief)) {
                        briefList.add(brief);
                    }
                }
            }
            //3-处理“分类详表（导入）”数据入库
            if (DETAIL_SHEET_INDEX == sheetIndex) {
                //获取表头下的数据
                List<IcmsCustomsDetailDto> detailTemps = ExcelImportUtil.importExcel(file.getInputStream(),
                        IcmsCustomsDetailDto.class, params);
                for (IcmsCustomsDetailDto detailDto : detailTemps) {
                    if (!handleExcelInfo.checkObjAllFieldsIsNull(detailDto)) {
                        detailDtoList.add(detailDto);
                    }
                }
            }
            //处理【分类简表】
            //排除“件号”为空的数据(即汇总数据),在入库
            if (!CollectionUtils.isEmpty(briefList) && sheetIndex == BRIEF_SHEET_INDEX) {
                briefList = briefList.stream().filter(a -> a.getPartNo() != null && !a.getPartNo().isEmpty())
                        .collect(Collectors.toList());
                String briefContractNo = contractNo;
                String briefExportCompany = exportCompany;
                String briefHeaderId = headerId;
                briefList.forEach(brief -> {
                    brief.setCustomsHeaderId(briefHeaderId);
                    brief.setContractNo(briefContractNo);
                    brief.setExportCompany(briefExportCompany);
                    icmsCustomsBriefMapper.insert(brief);
                });
            }
            //处理【分类详表】
            //排除“件号”为空的数据
            if (!CollectionUtils.isEmpty(detailDtoList) && DETAIL_SHEET_INDEX == sheetIndex) {
                detailDtoList = detailDtoList.stream().filter(b -> b.getPartNo() != null && !b.getPartNo().isEmpty())
                        .collect(Collectors.toList());
                String detailContractNo = contractNo;
                String detailExportCompany = exportCompany;
                String detailHeaderId = headerId;
                detailDtoList.forEach(detailDto -> {
                    detailDto.setCustomsHeaderId(detailHeaderId);
                    detailDto.setContractNo(detailContractNo);
                    detailDto.setExportCountry(detailExportCompany);
                });
                Map<String, IcmsCustomsDetailDto> detailDtoMap = detailDtoList.stream()
                        .collect(Collectors.toMap(dto -> dto.getPartName()+"+"+dto.getPartNo(), Function.identity()));
                //申报要素中的几个大项即为分类项表中的父项，且父项的“税率”字段为中文，与数据库double类型不符，在这里需要转换一次
                //把elementList中的每一个对象的partName+partNo作为key,分离出第一个Map;剩下的是为第二个Map
                Map<String, IcmsCustomsDetailDto> firstMap = elementList.stream().collect(Collectors.toMap(
                        element -> element.getPartName() + "+" + element.getPartNo(),
                        icmsCustomsElements -> detailDtoMap.get(icmsCustomsElements.getPartName() + "+" + icmsCustomsElements.getPartNo())));
                Map<String, IcmsCustomsDetailDto> secondMap  = new HashMap<>(detailDtoMap);
                firstMap.forEach((partNameNo, icmsCustomsDetailDto) -> secondMap.remove(partNameNo));
                //将firstMap中所有“税率”这个字段置空
                firstMap.forEach((partNameNo, icmsCustomsDetailDto) -> {
                    icmsCustomsDetailDto.setPid("0");
                    icmsCustomsDetailDto.setHasChild("1");
                    icmsCustomsDetailDto.setTaxRate("");
                });
                List<IcmsCustomsDetailDto> firstDetailDtos = firstMap.values().stream().collect(Collectors.toList());
                List<IcmsCustomsDetailDto> secondDetailsDtos = secondMap.values().stream().collect(Collectors.toList());
                List<IcmsCustomsDetail> firstDetails = trans(firstDetailDtos);
                List<IcmsCustomsDetail> secondDetails = trans(secondDetailsDtos);
                Map<String, List<IcmsCustomsDetail>> tempMap = secondDetails.stream()
                        .collect(Collectors.groupingBy(IcmsCustomsDetail::getHsCode));
                //firstDetails入库后得到的id将作为secondDetails入库后的父Id
                firstDetails.forEach(c -> {
                    icmsCustomsDetailMapper.insert(c);
                    IcmsCustomsDetail detail = new IcmsCustomsDetail();
                    detail.setPartNo(c.getPartNo());
                    detail.setHsCode(c.getHsCode());
                    QueryWrapper<IcmsCustomsDetail> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(IcmsCustomsDetail::getPartNo, c.getPartNo());
                    queryWrapper.lambda().eq(IcmsCustomsDetail::getHsCode, c.getHsCode());
                    queryWrapper.lambda().eq(IcmsCustomsDetail::getContractNo, c.getContractNo());
                    String id = icmsCustomsDetailMapper.selectOne(queryWrapper).getId();
                    List<IcmsCustomsDetail> tempList = tempMap.get(c.getHsCode());
                    tempList.forEach(temp -> {
                        temp.setPid(id);
                        icmsCustomsDetailMapper.insert(temp);
                    });
                });
            }
        }
        return Result.OK("导入成功！");
    }

    /**List<IcmsCustomsDetailDto>转List<IcmsCustomsDetail>*/
    private List<IcmsCustomsDetail> trans(List<IcmsCustomsDetailDto> list) {
        List<IcmsCustomsDetail> icmsCustomsDetails = list.stream()
                .map(icmsCustomsDetailDto -> {
                    IcmsCustomsDetail icmsCustomsDetail = new IcmsCustomsDetail();
                    icmsCustomsDetail.setId(icmsCustomsDetailDto.getId());
                    icmsCustomsDetail.setPid(icmsCustomsDetailDto.getPid());
                    icmsCustomsDetail.setCreateBy(icmsCustomsDetailDto.getCreateBy());
                    icmsCustomsDetail.setCreateTime(icmsCustomsDetailDto.getCreateTime());
                    icmsCustomsDetail.setUpdateBy(icmsCustomsDetailDto.getUpdateBy());
                    icmsCustomsDetail.setUpdateTime(icmsCustomsDetailDto.getUpdateTime());
                    icmsCustomsDetail.setSysOrgCode(icmsCustomsDetailDto.getSysOrgCode());
                    icmsCustomsDetail.setCustomsHeaderId(icmsCustomsDetailDto.getCustomsHeaderId());
                    icmsCustomsDetail.setContractNo(icmsCustomsDetailDto.getContractNo());
                    icmsCustomsDetail.setExportCountry(icmsCustomsDetailDto.getExportCountry());
                    icmsCustomsDetail.setPartNo(icmsCustomsDetailDto.getPartNo());
                    icmsCustomsDetail.setPartName(icmsCustomsDetailDto.getPartName());
                    icmsCustomsDetail.setQty(icmsCustomsDetailDto.getQty());
                    icmsCustomsDetail.setTotalWeight(icmsCustomsDetailDto.getTotalWeight());
                    icmsCustomsDetail.setVolume(icmsCustomsDetailDto.getVolume());
                    icmsCustomsDetail.setHsCode(icmsCustomsDetailDto.getHsCode());
                    icmsCustomsDetail.setHsDodeDesc(icmsCustomsDetailDto.getHsDodeDesc());
                    icmsCustomsDetail.setTotalPrice(icmsCustomsDetailDto.getTotalPrice());
                    icmsCustomsDetail.setHasChild(icmsCustomsDetailDto.getHasChild());
                    if (!"".equals(icmsCustomsDetailDto.getTaxRate())) {
                        icmsCustomsDetail.setTaxRate(Double.parseDouble(icmsCustomsDetailDto.getTaxRate()));
                    }else {
                        icmsCustomsDetail.setTaxRate(null);
                    }
                    icmsCustomsDetail.setLegalUnit(icmsCustomsDetailDto.getLegalUnit());
                    return icmsCustomsDetail;
                }).collect(Collectors.toList());
        return icmsCustomsDetails;
    }
}
